﻿/*
 * @Autor: PK
 * @Date: 2021-03-31 16:36:36
 * @Description: 道路实现类
 */

using System;
using System.Diagnostics;
using O2DESNet.Distributions;
using ShkSimulation.carsharing;
using ShkSimulation.core.template.customer;
using ShkSimulation.core.util;

namespace ShkSimulation.carsharing.impl.elements {

    [Memento]
    public partial class Road : CarsharingRoad {

        public int LastStationId { get; internal set; }
        public int NextStationId { get; internal set; }
        
        public Station LastStation { get; internal set; }
        public Station NextStation { get; internal set; }
        
        protected DuplicateSortedList<DateTime, CarsharingTraveler> WaitServeList 
            = new DuplicateSortedList<DateTime, CarsharingTraveler>(DateTimeComparator.EarlyFirst);

        public void DispatcherArrive(Dispatcher traveler) {
            // TODO 强制半小时
            ScheduleDepart(traveler, TimeSpan.FromHours(0.5));
        }

        public override void TravelerArrive(CarsharingTraveler traveler) {
            if (traveler is Dispatcher dispatcher) {
                RoadDispatcherCounter.ObserveChange(1, ClockTime);
                if (dispatcher.Vehicle == null) {
                    DispatcherArrive(dispatcher);
                    return;
                }
            }
            Debug.Assert(RoadVehicleCounter.LastCount >= 0, $"RoadVehicleCounter.LastCount不应该:{RoadVehicleCounter.LastCount}");
            //仅对虚拟空间车辆计数，车辆依然进入系统
            RoadVehicleCounter.ObserveChange(1, ClockTime);
            if (RoadVehicleCounter.LastCount >= Capacity) { 
                //系统中顾客数量大于容量,进入虚拟空间
                VehicleInVirtualSpace.ObserveChange(1, ClockTime);
            }
            Vehicle vehicle = traveler.Vehicle as Vehicle;
            Debug.Assert(vehicle != null, "vehicle 不应为 null");
            vehicle.FuelCost = FuelCost;
            vehicle.Distance = RoadLength;
            vehicle.Price = Price;
            vehicle.TimeToArriveRoad = ClockTime;
            if (ServingVehicleCounter.LastCount < ServerCount)
                TravelerServe(traveler);
            else {
                WaitServeList.Add(ClockTime, traveler);
                QueuingVehicleCounter.ObserveChange(1, ClockTime);
            }
        }
        
        public override void TravelerServe(CarsharingTraveler traveler) {
            ServingVehicleCounter.ObserveChange(1, ClockTime);
            //计算新的服务率
            TimeSpan hourlyServiceRate = ServiceRateHelper.GetAverageServiceTime();
            TimeSpan serviceTime = Exponential.Sample(DefaultRS, hourlyServiceRate);
            ServiceTimeCounter.ObserveCount(serviceTime.TotalHours, ClockTime);
            ServiceIntervalCounter.ObserveCount((ClockTime - ServiceIntervalCounter.LastTime).TotalHours, ClockTime);
            ScheduleDepart(traveler, serviceTime);
        }
        
        public override void TravelerDepart(CarsharingTraveler traveler) {
            if (traveler is Dispatcher dispatcher) {
                RoadDispatcherCounter.ObserveChange(-1, ClockTime);
                if (dispatcher.Vehicle == null) {
                    dispatcher.EnterNextAgency();
                    return;
                }
            }
            ServingVehicleCounter.ObserveChange(-1, ClockTime);
            RoadVehicleCounter.ObserveChange(-1, ClockTime);
            ServedCustomerNumber.ObserveChange(1, ClockTime);
            traveler.EnterNextAgency();
            if (QueuingVehicleCounter.LastCount > 0) {
                QueuingVehicleCounter.ObserveChange(-1, ClockTime);
                TravelerServe(WaitServeList.RemoveFirstAndGetValue());
            }
        }

    }
}
